package com.orange.cloud.common.utils;


import com.orange.cloud.common.exception.ServiceException;

import java.time.LocalDate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author zhouhuiyang
 * @since 2020/9/10 16:34
 * 身份证验证
 */
public class IdentityCardUtil {

    /**
     * 身份证每一位对应的加权因子
     */
    private static final int[] DEFAULT_LOAD_FACTOR = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};

    private static final String[] VERIFY_CODE = {"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"};

    private static final Pattern PATTERN = Pattern.compile("^\\d{17}[\\d|x|X]$");

    /**
     * 校验身份证合法性
     *
     * @return true：合法  false：不合法
     */
    public static boolean identityCodeVerify(String identityCode) {
        Matcher matcher = PATTERN.matcher(identityCode);
        if (!matcher.matches()) {
            throw new ServiceException("illegal param for idNO : " + identityCode);
        }
        // 验证年月日
        int year = LocalDate.now().getYear();
        // 7-10位是出生年份，范围应该在1900-当前年份之间
        if (Integer.parseInt(identityCode.substring(6, 10)) < 1900 || Integer.parseInt(identityCode.substring(6, 10)) > year) {
            return false;
        }
        // 11-12位代表出生月份，范围应该在01-12之间
        if (Integer.parseInt(identityCode.substring(10, 12)) < 1 || Integer.parseInt(identityCode.substring(10, 12)) > 12) {
            return false;
        }
        // 13-14位是出生日期，范围应该在01-31之间
        if (Integer.parseInt(identityCode.substring(12, 14)) < 1 || Integer.parseInt(identityCode.substring(12, 14)) > 31) {
            return false;
        }
        // 计算前面17位数与加权因子相乘后的总和
        int sum = 0;
        for (int i = 0; i < DEFAULT_LOAD_FACTOR.length; i++) {
            int anInt = Integer.parseInt(String.valueOf(identityCode.charAt(i)));
            sum = sum + anInt * DEFAULT_LOAD_FACTOR[i];
        }
        // 取模获取校验码
        int verifyCodeIndex = sum % 11;
        return VERIFY_CODE[verifyCodeIndex].equalsIgnoreCase(identityCode.substring(17));
    }

}
